package com.bitwaffle.launcher;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.FilePermission;
import java.security.AccessController;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.plaf.basic.BasicProgressBarUI;
/**
* This class manages methods that create the frame and all the panels for the launcher
* @author TranquilMarmot
*
*/
public class Display {
/** URL to RSS feed to use in center window */
private static final String RSSFEED = "http://spoutupdate.tumblr.com/rss";
/** How many items from the feed to show */
private static final int NUMITEMS = 5;
/** Default size of launcher window */
private static final int DEFAULT_WIDTH = 886, DEFAULT_HEIGHT = 710;
/** Our main frame*/
public static JFrame frame;
/** All the better to start the game with */
public static JButton start;
/** Our progress bar */
public static JProgressBar progBar;
/** Checkbox to tell the launcher whether or not to look for updates from the server */
public static JCheckBox checkForUpdate;
/** Info string */
public static JLabel info = new JLabel("");
/**
* Creates the AWT window and fills it
*/
public static void createWindow(){
frame = new JFrame("Spaceout Pre-alpha Launcher");
frame.setLayout(new BorderLayout());
frame.add(createSouthernPanel(), BorderLayout.SOUTH);
frame.add(createCenterPane(), BorderLayout.CENTER);
// close the frame when its close button is clicked
frame.addWindowListener(new WindowAdapter(){
@Override
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
// set the icon and size
frame.setIconImage(Toolkit.getDefaultToolkit().getImage("res/images/icon.png"));
frame.setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
frame.setVisible(true);
}
/**
* @return The center pane
*/
private static JPanel createCenterPane(){
JPanel centerPane = new JPanel();
centerPane.setLayout(new BorderLayout());
//centerPane.add(createInfoPane(), BorderLayout.WEST);
centerPane.add(createRSSPane(), BorderLayout.CENTER);
return centerPane;
}
/**
* @return An RSS pane with the RSS feed define at the top of this class
*/
private static JScrollPane createRSSPane(){
JScrollPane rssPane = new JScrollPane();
rssPane.getVerticalScrollBar().setBackground(Color.black);
rssPane.getHorizontalScrollBar().setBackground(Color.black);
rssPane.getViewport().add(RSS2AWT.getRSSFeed(RSSFEED, NUMITEMS));
return rssPane;
}
/**
* @return The southern panel
*/
private static JPanel createSouthernPanel(){
JPanel south = new JPanel();
south.setLayout(new BorderLayout());
south.setBackground(Color.black);
south.setForeground(Color.green);
south.add(createLogoAndCheckBox(), BorderLayout.WEST);
south.add(createButtonPanel(), BorderLayout.EAST);
// add info label
info.setForeground(Color.green);
south.add(info, BorderLayout.CENTER);
return south;
}
/**
* @return Panel with logo and download updates checkbox
*/
private static JPanel createLogoAndCheckBox(){
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add(createLogo(), BorderLayout.WEST);
panel.add(createUpdateCheckBox(), BorderLayout.EAST);
panel.setBackground(Color.black);
return panel;
}
/**
* @return Logo for Spaceout
*/
private static JLabel createLogo(){
// TODO make this have some sort of logo (might have to download it from the server)
JLabel spout = new JLabel(" SPACEOUT ");
spout.setBackground(Color.black);
spout.setForeground(Color.green);
return spout;
}
/**
* @return Checkbox to tell whether or not to check for updates
*/
private static JCheckBox createUpdateCheckBox(){
checkForUpdate = new JCheckBox(" Check for updates ");
checkForUpdate.setSelected(true);
checkForUpdate.addActionListener(getCheckBoxListener());
checkForUpdate.setBackground(Color.black);
checkForUpdate.setForeground(Color.green);
return checkForUpdate;
}
/**
* @return Listener for the update checkbox
*/
private static ActionListener getCheckBoxListener(){
return new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
if(!Launcher.serverFound){
if(!Launcher.filesExist()){
info.setText("ERROR: Server not found!");
start.setText("No game files!");
start.setEnabled(false);
} else{
info.setText("ERROR: Server not found! Game files exist, though!");
start.setText("Start Game");
start.addActionListener(getLaunchListener());
}
} else{
JCheckBox boxxy = (JCheckBox) e.getSource();
// basically just switch the state of the start button
if(boxxy.isSelected()){
if(!Launcher.filesExist()){
start.setText("Download Game (" + Launcher.totalFileSize() + " bytes)");
start.removeActionListener(start.getActionListeners()[0]);
start.addActionListener(getDownloadListener());
} else if(Launcher.updateRequired()){
start.setText("Update Game (from " + Launcher.localVersion + " to " + Launcher.serverVersion + ")");
start.removeActionListener(start.getActionListeners()[0]);
start.addActionListener(getDownloadListener());
} else{
start.setText("Start Game");
start.removeActionListener(start.getActionListeners()[0]);
start.addActionListener(getLaunchListener());
}
} else{
if(!Launcher.filesExist()){
start.setText("Download Game (" + Launcher.totalFileSize() + " bytes)");
start.removeActionListener(start.getActionListeners()[0]);
start.addActionListener(getDownloadListener());
}else{
start.setText("Start Game");
start.removeActionListener(start.getActionListeners()[0]);
start.addActionListener(getLaunchListener());
}
}
}
}
};
}
/**
* @return A panel with some buttons on it
*/
private static JPanel createButtonPanel(){
JPanel buttons = new JPanel();
buttons.setLayout(new FlowLayout());
JPanel sep = new JPanel();
sep.setBackground(Color.black);
JPanel sep2 = new JPanel();
sep2.setBackground(Color.black);
buttons.add(createProgressBar());
buttons.add(sep);
buttons.add(sep2);
buttons.add(createStartButton());
buttons.setBackground(Color.black);
return buttons;
}
/**
* @return A button that starts the game
*/
private static JButton createStartButton(){
// if there's no server and files exist, let the game be played, otherwise don't
if(!Launcher.serverFound){
if(!Launcher.filesExist()){
info.setText("ERROR: Server not found!");
start = new JButton("No game files!");
start.setEnabled(false);
} else{
info.setText("ERROR: Server not found! Game files exist, though!");
start = new JButton("Start Game");
start.addActionListener(getLaunchListener());
}
} else{
if(!Launcher.filesExist()){
info.setText("Using " + Launcher.getHomeDir() + " as home directory");
start = new JButton("Download Game (" + Launcher.totalFileSize() + " bytes)");
start.addActionListener(getDownloadListener());
}else if(Launcher.updateRequired()){
start = new JButton("Update Game (from " + Launcher.localVersion + " to " + Launcher.serverVersion + ")");
start.addActionListener(getDownloadListener());
}else{
progBar.setVisible(false);
start = new JButton("Start Game");
start.addActionListener(getLaunchListener());
}
}
start.setBackground(Color.black);
start.setForeground(Color.green);
return start;
}
/**
* @return An action listener that launches the game
*/
private static ActionListener getLaunchListener(){
return new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
Launcher.launchGame();
System.exit(0);
}
};
}
/**
* @return An action listener that downloads and extracts files
*/
private static ActionListener getDownloadListener(){
return new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
if(!FileOps.hasWriteAccess(Launcher.workingDir)){
chooseNewHomeDir();
if(Launcher.filesExist()){
Launcher.localVersion = Launcher.getLocalVersion();
start.setText("Start Game");
start.removeActionListener(start.getActionListeners()[0]);
start.addActionListener(getLaunchListener());
}
} else{
progBar.setVisible(true);
start.setText("Downloading...");
start.setEnabled(false);
Thread t = new Thread(){
@Override
public void run(){
Launcher.downloadAndExtractFiles();
progBar.setVisible(false);
start.setEnabled(true);
start.setText("Start Game");
start.removeActionListener(start.getActionListeners()[0]);
start.addActionListener(getLaunchListener());
}
};
t.start();
}
}
};
}
private static void chooseNewHomeDir(){
try{
AccessController.checkPermission(new FilePermission(Launcher.workingDir, "write"));
} catch (java.security.AccessControlException e){
}
int ret = JOptionPane.showConfirmDialog(null, "Error: Couldn't get write access to " + Launcher.workingDir + "\nSelect a different directory?", "Write Access Denied", JOptionPane.YES_NO_OPTION, JOptionPane.ERROR_MESSAGE);
if(ret == JOptionPane.YES_OPTION){
JFileChooser chooser = new JFileChooser();
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int returnVal = chooser.showOpenDialog(null);
if(returnVal == JFileChooser.APPROVE_OPTION) {
Launcher.workingDir = chooser.getSelectedFile().getAbsolutePath();
if(!Launcher.workingDir.endsWith(System.getProperty("file.separator")))
Launcher.workingDir += System.getProperty("file.separator");
Display.info.setText("Using " + Launcher.workingDir + " as home directory");
}
}
}
/**
* @return The progress bar
*/
private static JProgressBar createProgressBar(){
progBar = new JProgressBar();
progBar.setValue(0);
progBar.setStringPainted(true);
progBar.setBackground(Color.black);
progBar.setForeground(Color.green);
progBar.setUI(new BasicProgressBarUI() {
protected Color getSelectionBackground() { return Color.green; }
protected Color getSelectionForeground() { return Color.black; }
});
progBar.setVisible(false);
return progBar;
}
}